package jp.co.heartsoft.gpssearch;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;

import jp.co.heartsoft.gpssearch.R.id;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.ProgressDialog;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.Button;
import android.widget.TextView;
import android.widget.EditText;
import android.widget.Spinner;
import android.text.SpannableStringBuilder;
import android.content.Intent;

public class GpsSearchActivity extends Activity implements LocationListener{
	private static final String TAG = "HsGpsSearchLog";

	View view;

	ProgressDialog progress;

	LocationManager locManager;

	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.main);

        // ボタンにイベントを紐付ける。
        Button bt = (Button)findViewById(R.id.doSearch);
        bt.setOnClickListener(doSearchClick);

        locManager = (LocationManager) getSystemService(LOCATION_SERVICE);
    }

    @Override
    protected void onResume() {
    	progress = new ProgressDialog(this);
    	progress.setMessage(getText(R.string.progress_location));
    	progress.show();

    	locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);

    	super.onResume();
    }

    @Override
    protected void onPause() {
    	super.onPause();
    }

	@Override
	public void onLocationChanged(Location location) {
		locManager.removeUpdates(this);

		new GeocodingTask().execute(location);
	}

	@Override
	public void onProviderDisabled(String provider) {
		// TODO 自動生成されたメソッド・スタブ

	}

	@Override
	public void onProviderEnabled(String provider) {
		// TODO 自動生成されたメソッド・スタブ

	}

	@Override
	public void onStatusChanged(String provider, int status, Bundle extras) {
		// TODO 自動生成されたメソッド・スタブ

	}

	/**
	 * Google Geocoding API タスククラス。
	 */
	private class GeocodingTask extends AsyncTask<Location, Void, HashMap<String, String>>{

		@Override
		protected HashMap<String, String> doInBackground(Location... params) {
			String resData = "";
			String str;

			try {
				String uri = createGeocodingRequestUri(params);
				Log.d(TAG, "URL : " + uri);
				URL url = new URL(uri);
				HttpURLConnection connection = (HttpURLConnection)url.openConnection();
				connection.setRequestMethod("GET");
				connection.connect();
				InputStreamReader inputReader = new InputStreamReader(connection.getInputStream(), "UTF-8");
				BufferedReader bufferReader = new BufferedReader(inputReader);

				while (null != (str = bufferReader.readLine())) {
					resData = resData + str;
				}
				bufferReader.close();
				connection.disconnect();

				Log.d(TAG, resData);
			} catch (MalformedURLException e) {
				Log.e(TAG, "MalformedURLException: " + e);
				e.printStackTrace();
			} catch (IOException e) {
				Log.e(TAG, "IOException: " + e);
				e.printStackTrace();
			}

			JSONObject resJson = null;
			try {
				resJson = new JSONObject(resData);
			} catch (JSONException e) {
				Log.e(TAG, "JSONException : " + e);
				e.printStackTrace();
			}

			return getAddress(resJson);
		}

		@Override
		protected void onPostExecute(HashMap<String, String> result) {
			String ad = "";
			if (null != progress){
				progress.dismiss();
			}

			ad = createAddressStr(5, result);

			((TextView)findViewById(R.id.address)).setText(ad);
		}
	}

	/**
	 * 住所取得。
	 * @param resJson
	 * @return
	 * prefecture  => 都道府県
	 * city        => 市郡
	 * ward        => 区
	 * town        => 町村
	 * houseNumber => 番地
	 */
	private HashMap<String, String> getAddress(JSONObject resJson) {
		JSONArray results;
		HashMap<String, String> address = new HashMap<String, String>();
		try {
			results = resJson.getJSONArray("results");
			JSONArray addressComponents = results.getJSONObject(0).getJSONArray("address_components");
			address.put("prefecture", addressComponents.getJSONObject(4).getString("long_name"));
			address.put("city", addressComponents.getJSONObject(3).getString("long_name"));
			address.put("ward", addressComponents.getJSONObject(2).getString("long_name"));
			address.put("town", addressComponents.getJSONObject(1).getString("long_name"));
			address.put("houseNumber", addressComponents.getJSONObject(0).getString("long_name"));
		} catch (JSONException e) {
			Log.e(TAG, "JSONException : " + e);
			e.printStackTrace();
		}

		return address;
	}

	/**
	 * 住所取得検索URIの生成。
	 * @param pos
	 * @return
	 */
	private String createGeocodingRequestUri(Location... pos) {
		Uri.Builder uri = new Uri.Builder();
		uri.scheme("https");
		uri.authority("maps.googleapis.com");
		uri.path("/maps/api/geocode/json");
		uri.appendQueryParameter("latlng", pos[0].getLatitude() + "," + pos[0].getLongitude());
		uri.appendQueryParameter("sensor", "false");
		uri.appendQueryParameter("language", "ja");

		return uri.toString();
	}

	/**
	 * @param level 住所レベル[1:県,2:市,3:区,4:町,5:番地]
	 * @param addressInfo 住所情報
	 * @return 各レベルに合わせた住所を文字列化したもの。
	 */
	private String createAddressStr(int level, HashMap<String, String> addressInfo) {
		String ad;
		switch (level) {
		case 1:
			ad = addressInfo.get("prefecture");
			break;
		case 2:
			ad = addressInfo.get("prefecture") + addressInfo.get("city");
			break;
		case 3:
			ad = addressInfo.get("prefecture") + addressInfo.get("city") + addressInfo.get("ward");
			break;
		case 4:
			ad = addressInfo.get("prefecture") + addressInfo.get("city") + addressInfo.get("ward")
			+ addressInfo.get("town");
			break;
		case 5:
			ad = addressInfo.get("prefecture") + addressInfo.get("city") + addressInfo.get("ward")
			+ addressInfo.get("town") + addressInfo.get("houseNumber");
			break;
		default:
			ad = addressInfo.get("prefecture") + addressInfo.get("city") + addressInfo.get("ward")
			+ addressInfo.get("town") + addressInfo.get("houseNumber");
			break;
		}
		return ad;
	}

	/**
	 * 検索ボタンをクリック押下時の動作を記述。
	 * １．住所とキーワードから検索URIを作成。
	 * ２．[1.]で作成したURIをブラウザに渡して起動する。
	 */
	private OnClickListener doSearchClick = new OnClickListener() {
		public void onClick(View v) {
			// 住所の値を取得.
			EditText editText = (EditText)findViewById(R.id.address);
			String addStr = editText.getText().toString();
			// 検索キーワードの取得.
			Spinner spinner = (Spinner)findViewById(R.id.searchOptionList);
			String keyWord = spinner.getSelectedItem().toString();

			Uri searchUri = createSearchUri(addStr, keyWord);
			Intent i = new Intent(Intent.ACTION_VIEW, searchUri);
			startActivity(i);
		}
	};

	/**
	 * 検索URIを生成する。
	 * @param searchWord
	 * @return
	 */
	private Uri createSearchUri(String add, String keyWord) {
		Uri.Builder builder = new Uri.Builder();
		builder.scheme("http");
		builder.authority("www.google.co.jp");
		builder.path("/search");
		builder.appendQueryParameter("ie", "utf-8");
		builder.appendQueryParameter("oe", "utf-8");
		builder.appendQueryParameter("lr", "lang_ja");
		String baseUri = builder.toString();
		// '+'をエンコードしたくないため、文字列として扱う。
		String words = add + "+" + keyWord;
		String searchUri = baseUri + "&q=" + words;

		return Uri.parse(searchUri);
	}
}
